package org.snia.server.security;

import java.util.Map;

import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.TextInputCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;

import org.snia.util.ServiceUtils;


public class SecurityLoginModule implements LoginModule{
//	private Subject subject;
	private CallbackHandler callbackHandler;
//	private Map<String, ?> sharedState;
//	private Map<String, ?> options;
	
	// the authentication status
	private boolean succeeded = false;
	private boolean commitSucceeded = false;
	
	// configurable option
	private boolean debug = false;
	
	private String securitySource; //校验源
	private String accessKey;//授权码
	private String signature;//访问签名
	private String date;//访问日期
	private String resourcePath;//请求路径
	private String httpVerb;//Http方法
	
	@Override
	public boolean abort() throws LoginException {
		if (this.succeeded == false) {
			return false;
		} else if (this.succeeded == true && this.commitSucceeded == false) {
			// login succeeded but overall authentication failed
			this.succeeded = false;
			this.securitySource = null;
			this.accessKey = null;
			this.signature = null;
			this.date = null;
			this.resourcePath = null;
			this.httpVerb = null;
		} else {
			// overall authentication succeeded and commit succeeded,
			// but someone else's commit failed
			logout();
		}
		return true;
	}

	@Override
	public boolean commit() throws LoginException {
		if (this.succeeded == false) {
			return false;
		}
		// in any case, clean out state
		this.securitySource = null;
		this.accessKey = null;
		this.signature = null;
		this.date = null;
		this.resourcePath = null;
		this.httpVerb = null;
		this.commitSucceeded = true;
		return true;
	}

	@Override
	public void initialize(Subject subject, CallbackHandler callbackHandler,
			Map<String, ?> sharedState, Map<String, ?> options) {
//		this.subject = subject;
		this.callbackHandler = callbackHandler;
//		this.sharedState = sharedState;
//		this.options = options;

		// initialize any configured options
		this.debug = "true".equalsIgnoreCase((String) options.get("debug"));
		
	}

	@Override
	public boolean login() throws LoginException {
		// prompt for a user name and password
		if (this.callbackHandler == null)
			throw new LoginException("Error: no CallbackHandler available "
					+ "to garner authentication information from the user");

		Callback[] callbacks = new Callback[4];
		callbacks[0] = new TextInputCallback("Authorization: ");
		callbacks[1] = new TextInputCallback("Http Verb: ");
		callbacks[2] = new TextInputCallback("Resource Path: ");
		callbacks[3] = new TextInputCallback("Date: ");



		try {
			this.callbackHandler.handle(callbacks);
			String authorization = ((TextInputCallback) callbacks[0]).getText(); 
			if(authorization != null){
				int i = authorization.indexOf(" ");
				if(i > 1){
					this.securitySource = authorization.substring(0, i);
				}
				int j  = authorization.indexOf(":");
				this.accessKey = authorization.substring(i+1, j);
				this.signature = authorization.substring(j+1);
			}
			
			this.httpVerb = ((TextInputCallback) callbacks[1]).getText(); 
			this.resourcePath = ((TextInputCallback) callbacks[2]).getText(); 
			this.date = ((TextInputCallback) callbacks[3]).getText(); 
		} catch (java.io.IOException ioe) {
			throw new LoginException(ioe.toString());
		} catch (UnsupportedCallbackException uce) {
			throw new LoginException("Error: " + uce.getCallback().toString()
					+ " not available to garner authentication information "
					+ "from the user");
		}

		// print debugging information
		if (debug) {
			System.out.println("\t\t[SecurityLoginModule] "
					+ "request entered Pool Name: " + this.securitySource);
			System.out.println("\t\t[SecurityLoginModule] "
					+ "request entered AccessKey: " + this.accessKey);
			System.out.println("\t\t[SecurityLoginModule] "
					+ "request entered Signature: " + this.signature);			
			System.out.println();
		}

		
//		String secretKey="Ex6FioaA7c/JlACUeBdmp7Soqm9YwyxKPUWQuATi";
		//TODO 从数据库中根据授权码获取访问密钥
//		JdbcTemplate jdbc = DAOUtil.getJdbcDao(); 
//		String secretKey = (String) jdbc
//		.queryForObject(
//				"select secretkey from cm_credentials where accesskey = ? ",
//				new Object[] { this.accessKey }, String.class);
//		if(secretKey == null){
//			throw new LoginException("Error: user not found in system");
//		}
		String secretKey = ""; //从系统中获取
		//系统根据请求生成新的签名，用该签名与传入的签名进行比较
		String canonicalString = ServiceUtils.stringToSign(httpVerb, resourcePath, secretKey,
				this.date, null);

		String in_signature = ServiceUtils.signWithHmacSha1(secretKey, canonicalString);
		System.out.println(this.signature + ":" + in_signature);
		if(this.signature.equals(in_signature)){
			System.out.println("true");
			this.succeeded = true;
			return true;
		}
		this.succeeded = false;
		return false;
	}

	@Override
	public boolean logout() throws LoginException {
		this.succeeded = false;
		this.succeeded = commitSucceeded;
		return true;
	}
}
